import type { App } from 'vue'

interface Message {
  type: string;
  data: any
}

export class SocketClient {
  socket: WebSocket | null = null;
  baseUrl: string;
  options: object;
  isConnect =  false;
  connectContext: { url: string | undefined; } = {};
  callMap: Map<string, Array[]>;

  constructor(baseUrl: string, options: object) {
    this.baseUrl = baseUrl
    this.options = options
    this.callMap = new Map()
  }

  /**
   * 连接
   */
  async connect(options: {url?: string, params?: object, query?: object}) {
    if (this.isConnect) return
    
    let url = options.url
    url = url? this.baseUrl + url : this.baseUrl

    if (this.socket != null || this.socket != undefined) {
      console.log(this.socket);
      return
      // this.socket?.close()
    }
    this._connect(url).then(() => {
      this.socket.onmessage = (e) => {
        // const type = e.data
        const message: Message = JSON.parse(e.data)
        // console.log(message.type);
        const list = this.callMap.get(message.type) || []
        console.log(list);
        for (const fun of list) {
          fun(message)
        }
      }
    })
  }

  reConnect() {
    this._connect(this.connectContext.url)
  }
  _connect(url: any) {
    return new Promise((resolve, reject) => {
      this.socket = new WebSocket(url)
      this.socket.onopen = (e) => {
      this.isConnect = true
      this.connectContext = {
          url
      }
      resolve()
      }
    })
  }

  close() {
    this.socket?.close()
    this.socket = null
  }

  send(message: any) {
    // const data = {
    //   type: event,
    //   data: message
    // }
    this.socket?.send(JSON.stringify(message))
  }

  on(event: string, callback: Function) {
    let arr = this.callMap.get(event)
    if (arr == null || arr == undefined) {
      this.callMap.set(event, [callback])
      return
    }
    
    this.callMap.get(event).push(callback)
    // console.log('on event:', event);
    
    // this.socket!.onmessage = (e: any) => {
    //   // console.warn(event);
      
    //   const message: Message = JSON.parse(e.data)
    //   // console.log(message.type);
      
    //   if (message.type == event) {
    //     callback(message)
    //   }
    // }
  }
}

export default {
    install: (app: App, { connection, options }: any) => {
      var socket = new SocketClient(connection, options)
      app.config.globalProperties.$socket = socket
      app.provide('socket', socket)
    }
}

